#ifndef __ZEN_JSLCONVERT_HPP__
#define __ZEN_JSLCONVERT_HPP__

#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
#include <JSL.hpp>

namespace zen {
namespace utils {

class JSLConvert {
public:
	inline static btVector3 toBtVector3(const jsl::Node* node) {
		return btVector3(node->at(0)->asFloat(), node->at(1)->asFloat(), node->at(2)->asFloat());
	}
	inline static btVector4 toBtVector4(const jsl::Node* node) {
		return btVector4(node->at(0)->asFloat(), node->at(1)->asFloat(), node->at(2)->asFloat(), node->at(3)->asFloat());
	}

    inline static bool load(glm::vec2 &vec, const jsl::Node* node) {
        if (node == 0 || node->size() < 2)
            return false;
        try {
            vec[0] = node->at(0)->asFloat();
            vec[1] = node->at(1)->asFloat();
        } catch (const std::exception &) {
            return false;
        }
        return true;
    }

    inline static bool save(jsl::Node* node, const glm::vec2 &vec) {
        if (node == 0)
            return false;
        try {
            node->set("[0]", vec[0]);
            node->set("[1]", vec[1]);
        } catch (const std::exception &) {
            return false;
        }
        return true;
    }

    inline static bool load(glm::vec3 &vec, const jsl::Node* node) {
        if (node == 0 || node->size() < 3)
            return false;
        try {
            vec[0] = node->at(0)->asFloat();
            vec[1] = node->at(1)->asFloat();
            vec[2] = node->at(2)->asFloat();
        } catch (const std::exception &) {
            return false;
        }
        return true;
    }

    inline static bool save(jsl::Node* node, const glm::vec3 &vec) {
        if (node == 0)
            return false;
        try {
            node->set("[0]", vec[0]);
            node->set("[1]", vec[1]);
            node->set("[2]", vec[2]);
        } catch (const std::exception &) {
            return false;
        }
        return true;
    }

    inline static bool load(glm::vec4 &vec, const jsl::Node* node) {
        if (node->isNull() || node->size() < 4)
            return false;
        vec[0] = node->at(0)->asFloat();
        vec[1] = node->at(1)->asFloat();
        vec[2] = node->at(2)->asFloat();
        vec[3] = node->at(3)->asFloat();
        return true;
    }

    inline static void load(glm::vec4 &vec, const jsl::Node* node, const glm::vec4 &alternative) {
        if (node->isNull() || node->size() < 4) {
            vec = alternative;
		} else {
            vec[0] = node->at(0)->asFloat();
            vec[1] = node->at(1)->asFloat();
            vec[2] = node->at(2)->asFloat();
            vec[3] = node->at(3)->asFloat();
		}
    }

    inline static bool save(jsl::Node* node, const glm::vec4 &vec) {
        if (node == 0)
            return false;
        try {
            node->set("[0]", vec[0]);
            node->set("[1]", vec[1]);
            node->set("[2]", vec[2]);
            node->set("[3]", vec[3]);
        } catch (const std::exception &) {
            return false;
        }
        return true;
    }

    inline static bool load(glm::mat4 &matrix, const jsl::Node* node) {
        if (node == 0 || node->size() < 16)
            return false;
        try {
            for (int i = 0; i < 16; i++)
                matrix[i / 4][i % 4] = node->at(i)->asFloat();
        } catch (const std::exception &) {
            return false;
        }
        return true;
    }

    inline static bool load(jsl::Node* node, const glm::mat4 &matrix) {
        if (node == 0)
            return false;
        try {
            for (int i = 0; i < 16; i++)
            	node->set("[" + boost::lexical_cast<std::string>(i) + "]", matrix[i / 4][i % 4]);
        } catch (const std::exception &) {
            return false;
        }
        return true;
    }

};

} // namespace utils
} // namespace zen

#endif
